<?php
/**
 * 用户管理
 */
namespace app\common\model;

use think\Model;
use app\common\model\MemberLevel as MemberLevelModel;
use app\common\model\MemberCurrency as MemberCurrencyModel;

class Member extends Model
{
    protected $connection = 'mysql';

    protected $pk = 'id';

    protected $name = 'member';

    /**
     * 查询所有用户
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getAll(){
        return self::select()->toArray();
    }

    /**
     * 获取用户钱包
     * @param $mid  用户ID
     */
    public static function wallet($mid){
        return MemberCurrencyModel::member_renew($mid);
    }

    /**
     * 获取用户信息
     * @param $mid 用户ID
     * @return Member|array|mixed|Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getDetails($mid){
        $info = self::where('id',$mid)->field('username,pic,power,pid,mnemonic,mobile,status,type,position,direct,level_id,invitation,sign_time')->find();
        return $info;
    }

    /**
     * 根据用户地址查询用户
     * @param $address 用户地址
     * @return Member|array|mixed|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function address($address){
        return self::where('username',$address)->find();
    }

    /**
     * 根据助记词获取用户详情
     * @param $mnemonic 助记词
     * @return Member|array|mixed|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function mnemonic($mnemonic){
        return self::where('mnemonic',$mnemonic)->find();
    }

    /**
     * 根据密码查询助记词和私钥
     * @param $mid  用户ID
     * @param $password 密码
     * @return Member|array|mixed|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException\
     */
    public static function pass_mnemonic_key($mid){
        return self::where('id',$mid)->field('private_key,mnemonic')->find();
    }

    /**
     * 查询用户密码
     * @param $mid 用户ID
     * @return Member|array|mixed|Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function password($mid){
       $data = self::where('id',$mid)->field('password,login_cryptosalt')->find();
       return $data;
    }

    /**
     * 升级用户
     * @param $mid  用户ID
     * @param $level_id 等级ID
     */
    public static function upgrade_level($mid,$level_id){
        self::where('id',$mid)->update(['level_id'=>$level_id]);
    }

    /**
     * 修改币种数量
     * @param $mid  用户ID
     * @param $num 数量
     * @param $name 币种名称
     * @param $state 修改状态
     */
    public static function up_currency($mid,$num,$name,$state){
        return self::where('id', $mid)->$state($name, $num)->update();
    }

    /**
     * 查询层级关系图
     * @param $mid  用户ID array | int
     * @param $ceng -1为无限层 | N != -1 则查询N层内关系
     * @param int $num  当前层级
     * @param array $member 已查询出来的用户
     */
    public static function member_relationship($mid,$ceng = -1,$num = 1,$member = []){
        if(empty($member)) $member['all'] = [];
        //非数组
        if(!is_array($mid)) $mid = [$mid];
        //查询下级用户
        $b_member = self::whereIn('pid',$mid)->where('status',1)->field('id,username,level_id,pid')->select()->toArray();
        if(!empty($b_member) && ($ceng != 0 || $ceng == -1)){    //判断有下级用户,以及层级未结束
            $mid = [];
            foreach ($b_member as $v){
                $v['push_num'] = self::where('pid',$v['id'])->count();
                $v['push_node'] = self::where('pid',$v['id'])->where('level_id','>','1')->count();  //节点人数

                $level = MemberLevel::getDetails($v['level_id']);
                $v['level'] = $level['level'];
                //层级用户
                $member[($num-1)][$v['id']] = $v;
                //记录所有用户
                $member['all'][$v['id']] = $v;  //我线下所有用户
                $mid[] = $v['id'];  //可查询的关系ID
            }

            $member = self::member_relationship($mid,$ceng-1,$num+1,$member);
        }

        return $member;
    }

    /**
     * 查询层级关系图
     * @param $mid  用户ID array | int
     * @param $ceng -1为无限层 | N != -1 则查询N层内关系
     * @param int $num  当前层级
     * @param array $member 已查询出来的用户
     */
    public static function member_relationship_xiaohao($mid,$ceng = -1,$num = 1,$member = []){
        //非数组
        if(!is_array($mid)) $mid = [$mid];
        //查询下级用户
        $b_member = self::whereIn('pid',$mid)->where('status',1)->field('id,username,level_id,pid')->select()->toArray();

        if(!empty($b_member) && ($ceng != 0 || $ceng == -1)){    //判断有下级用户,以及层级未结束

            $mid = [];
            foreach ($b_member as $v){
                $v['push_num'] = self::where('pid',$v['id'])->count();  //直推人数
                $v['push_node'] = self::where('pid',$v['id'])->where('level_id','>','1')->count();  //节点人数

                $b =  'a'.(string)($num-1);
                $level = MemberLevel::getDetails($v['level_id']);
                $v['level'] = $level['level'];
                //层级用户
                $member[$b][] = $v;
                //记录所有用户
                $member['all'][] = $v;  //我线下所有用户
                $mid[] = $v['id'];  //可查询的关系ID
            }

            $member = self::member_relationship_xiaohao($mid,$ceng-1,$num+1,$member);
        }
        return $member;
    }

    /**
     * 查询层级关系图
     * @param $mid  上级用户ID
     * @return Member[]|array|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function member_diagram($mid = 1,$level){

        $member = self::where('pid',$mid)->field('id,username,position,level_id')->select();
        if(!empty($member)){
            $member = $member->toArray();
            foreach ($member as $k => $v){
                $member[$k]['name'] = $v['id'].' | '.substr($v['username'],-4).' | 等级:'.$level[$v['level_id']]['name'];
                $member[$k]['parent'] = $mid;
                $member[$k]['children'] = self::member_diagram($v['id'],$level);
            }
        }
        return $member;
    }

    /**
     *  矩阵关系图
     * @param $mid  上级用户ID
     * @return Member[]|array|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function member_matrix($position = 1,$level){
        $member = self::where('position',$position)->field('id,position,level_id')->find();
        $new_member = '';
        if(!empty($member)){
            $new_member =[
                'name'  =>  $member['id']." | 位置:".$member['position'].' | 等级:'.$level[$member['level_id']]['name'],
                'parent'    =>  $position,
            ];
            $m0 = self::member_matrix($member['position']*3-1,$level);
            $m1 = self::member_matrix($member['position']*3,$level);
            $m2 = self::member_matrix($member['position']*3+1,$level);
            if(!empty($m0)) $new_member['children'][] = $m0;
            if(!empty($m1)) $new_member['children'][] = $m1;
            if(!empty($m2)) $new_member['children'][] = $m2;
        }
        return $new_member;
    }

    /**
     * 统计所有用户指定余额
     * @param $currency 钱包种类
     * @return mixed
     */
    public static function count_wallet($currency){
        return self::where('status',1)->sum($currency);
    }

    /**
     * 获取最大用户余额
     * @param $currency 钱包种类
     * @return mixed
     */
    public static function max_wallet($currency){
        return self::where('status',1)->max($currency);
    }

    /**
     * 查询用户推荐人数
     * @param $mid  用户ID
     * @param $type  0:已激活用户 1:包括未激活用户
     * @return int  用户推荐数量
     */
    public static function recommend_num($mid,$type = 1){
        $count = self::where('pid',$mid)->where('status',1);
        if($type == 0) $count = $count->where('position','>',0);
        $sum = $count->count();
        return $sum;
    }

    /**
     * 递归上级 计算极差以及平级奖
     * @param $mid 用户ID
     * @param $num 分配数量
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function superior_extremely($mid,$num){
        $member = self::getDetails($mid)->toArray();
        //所有等级
        $level_List = MemberLevelModel::getMemberList();
        $level = [];
        $level['max'] = 0;  //最大等级
        //循环用户等级
        foreach ($level_List as $v){
            $level[$v['id']] = $v;
            if($v['level'] == 0) $level[0] = $v;    //初始等级
            if($level['max'] < $v['level']) $level['max'] = $v['level'];
        }

        $recursion['current'] = [
            'mid'   =>  $mid,
            'num'   =>  0,
            'bili'  =>  0,
            'level'   =>  $level[$member['level_id']],
            'pid'   =>  $member['pid'],
        ];
        $recursion['range'] = [];   //极差用户
        $recursion['current'] = []; //平级用户

        if(!empty($member['pid'])){
            return self::recursion_member($member['pid'],$num,$member['level_id'],$level,$recursion,0,$level[$member['level_id']]['mining_range']);
        }else{
            return $recursion;
        }
    }

    /**
     * 递归上级用户
     * @param $pid  上级用户ID
     * @param $num 剩余分配数量
     * @param $level_id 用户等级
     * @param $level_list   等级列表
     * @param $recursion   返回的用户数据
     * @param $ceng 所有层级
     * @param $range 当前极差
     * @param $ping 0：未取平级 1：已取平级
     */
    private static function recursion_member($pid,$num,$level_id,$level_list,$recursion,$ceng,$range = 0,$ping = 0){

        $member = self::getDetails($pid);
        if(empty($member)) return $recursion;   //没有该用户
        $member = $member->toArray();

        if($level_list[$member['level_id']]['level'] < $level_list[$level_id]['level']){    //判断等级小于上个用户
//            $ping = 0;  //重置已取平级
        }else{
            //极差
            if($level_list[$member['level_id']]['level'] > $level_list[$level_id]['level']){
                $ping = 0;  //重置已取平级
                if($level_list[$member['level_id']]['mining_range'] > $range){
                    //计算极差
                    $jicha = bcdiv(bcsub($level_list[$member['level_id']]['mining_range'],$range),100,2);
                    //计算极差所得数量
                    $suode = bcmul($num,$jicha,8);

                    $recursion['range'][$ceng] = [
                        'mid'   =>  $pid,
                        'num'   =>  $suode,
                        'bili'  =>  $jicha,
                        'level'   => $level_list[$member['level_id']],
                        'pid'   =>  $member['pid'],
                    ];
                    $ceng += 1; //层级+1
                    $range = $level_list[$member['level_id']]['mining_range'];  //重置极差
                    $level_id = $member['level_id'];    //重置等级
                }
            }elseif($ping == 0){
                //计算平级奖
                $ping = 1;
                if($level_list[$level_id]['mining_peer'] > 0){ //判断是否有平级奖
                    $recursion['current'][$ceng] = [
                        'mid'   =>  $pid,
                        'num'   =>  bcmul($num,bcdiv($level_list[$level_id]['mining_peer'],100,2),8), //计算平级所得数量
                        'bili'  =>  bcdiv($level_list[$level_id]['mining_peer'],100,2),
                        'level'   => $level_list[$member['level_id']],
                        'pid'   =>  $member['pid'],
                    ];
                }
            }
        }

        //判断是否有上级
        if(!empty($member['pid'])) $recursion = self::recursion_member($member['pid'],$num,$level_id,$level_list,$recursion,$ceng,$range,$ping);
        return $recursion;

    }

    /**
     * 算力奖励
     * @param $mid  用户ID
     * @param $power    算力
     * @return bool
     */
    public static function upPower($mid,$power){
        $member = self::where('id',$mid)->find();
        self::where('id',$mid)->update(['power'=>bcadd($member['power'],$power,8)]);
        return true;
    }
}